package com.starinside.wp.repository;

import com.starinside.wp.domain.NativeWithResultClass;
import org.hibernate.SQLQuery;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Service;

import javax.persistence.*;
import java.util.List;
import java.util.Objects;

/**
 * *******************************
 * Created by Tim.
 * form com.matt
 * on 2017/7/11
 * *******************************
 */
@Service
public class BaseNativeSqlRepository {

    @PersistenceUnit
    private EntityManagerFactory emf;

    /**
     * 查询多个属性
     * 返回List<Object[]>数组形式的List，数组中内容按照查询字段先后
     *
     * @param sql 原生SQL语句
     * @return
     */
    public List<Object[]> sqlArrayList(String sql) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNativeQuery(sql);
        List<Object[]> list = query.getResultList();
        em.close();
        return list;
    }

    /**
     * 查询多个属性
     * 返回List<Object>对象形式的List，Object为Class格式对象
     *
     * @param sql 原生SQL语句
     * @param obj Class格式对象
     * @return
     */
    public List sqlObjectList(String sql, Object obj) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNativeQuery(sql, obj.getClass());
        List list = query.getResultList();
        em.close();
        return list;
    }

    /**
     * 查询单个属性
     * 返回List<Object>对象形式的List，Object为对象数据类型
     *
     * @param sql 原生SQL语句
     * @return
     */
    public List sqlSingleList(String sql) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNativeQuery(sql);
        List list = query.getResultList();
        em.close();
        return list;
    }

    public Long sqlSingleResult(String sql) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNativeQuery(sql);
        Object o = query.getSingleResult();
        em.close();
        return Objects.isNull(o) ?0L:Long.valueOf(o.toString());
    }

    public Integer sqlResult(String sql) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNativeQuery(sql);
        Integer result = query.getFirstResult();
        em.close();
        return result;
    }

    public List sqlObjectList(String sqlTemplate, List params, Class clazz) {
        EntityManager em = emf.createEntityManager();

        Query query = null;
        List list = null;
        if(clazz.isAnnotationPresent(NativeWithResultClass.class)){
            query = em.createNativeQuery(sqlTemplate, clazz);

            for(int i = 0 ; i < params.size(); i++) {
                query.setParameter("" + (i+1), params.get(i));
            }

            list = query.unwrap(NativeQueryImpl.class).list();
        }else{
            query = em.createNativeQuery(sqlTemplate);

            for(int i = 0 ; i < params.size(); i++) {
                query.setParameter("" + (i+1), params.get(i));
            }

            list = query.unwrap(NativeQueryImpl.class)
                    .setResultTransformer(Transformers.aliasToBean(clazz))
                    .list();
        }

        em.close();

        return list;
    }


    public List sqlObjectList(String sql, Class clazz) {
        EntityManager em = emf.createEntityManager();
        List list = null;
        if(clazz.isAnnotationPresent(NativeWithResultClass.class)){
            Query query = em.createNativeQuery(sql, clazz);
            list = query.unwrap(NativeQueryImpl.class).list();
        }else{
            Query query = em.createNativeQuery(sql);
            list =query.unwrap(NativeQueryImpl.class)
                    .setResultTransformer(Transformers.aliasToBean(clazz))
                    .list();
        }

        em.close();
        return list;
    }

    public Long sqlLongResult(String sqlTemplate, List params) {
        EntityManager em = emf.createEntityManager();
        Query query = em.createNativeQuery(sqlTemplate);

        for(int i = 0 ; i < params.size(); i++) {
            query.setParameter("" + (i+1), params.get(i));
        }

        Object o = query.getSingleResult();
        em.close();
        return Objects.isNull(o) ?0L:Long.valueOf(o.toString());
    }

    protected static String formatSql(String sql, List<Object> params) {
        for (int i = 1; i <= params.size(); i++) {
            Object param = params.get(i - 1);
            if (param instanceof String) {
                param.toString().replace("\'", "");
                param = String.format("'%s'", param.toString());
                sql = sql.replace(":" + i, param.toString());
            } else {
                sql = sql.replace(":" + i, param.toString());
            }
        }
        return sql;
    }

}
